package com.brush.framework.web.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brush.common.constant.Constants;
import com.brush.common.constant.UserConstants;
import com.brush.common.core.domain.entity.SysDept;
import com.brush.common.core.domain.entity.SysRole;
import com.brush.common.core.domain.entity.SysUser;
import com.brush.common.core.domain.resp.AdminUserDetails;
import com.brush.common.core.domain.resp.AdminUserResp;
import com.brush.common.enums.UserStatus;
import com.brush.common.exception.ServiceException;
import com.brush.common.utils.MessageUtils;
import com.brush.common.utils.ip.AddressUtils;
import com.brush.common.utils.ip.IpUtils;
import com.brush.system.service.SysDeptService;
import com.brush.system.service.SysMenuService;
import com.brush.system.service.SysRoleService;
import com.brush.system.service.SysUserService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 后台用户登录和权限的业务逻辑实现
 */
@Log4j2
@Service
public class AdminUserDetailsServiceImpl implements UserDetailsService {

    /**
     * 后台用户表
     */
    @Autowired
    private SysUserService sysUserService;

    /**
     * 后台角色表
     */
    @Autowired
    private SysRoleService sysRoleService;

    /**
     * 后台菜单表
     */
    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 部门查询
     */
    @Autowired
    private SysDeptService sysDeptService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //1、根据用户名查询用户信息
        SysUser dbUser=this.sysUserService.getOne(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName,username)
        );

        if(Objects.isNull(dbUser)){
            log.info("登录用户：{} 不存在.", username);
            throw new ServiceException(MessageUtils.message("user.not.exists"));
        }

        if (UserStatus.DELETED.getCode().equals(dbUser.getDelFlag()))
        {
            log.info("登录用户：{} 已被删除.", username);
            throw new ServiceException(MessageUtils.message("user.password.delete"));
        }

        if (UserStatus.DISABLE.getCode().equals(dbUser.getStatus()))
        {
            log.info("登录用户：{} 已被停用.", username);
            throw new ServiceException(MessageUtils.message("user.blocked"));
        }

        // 密码判断，不在这里做，springsecurity自动帮你做的

         //查询用户所在部门
        SysDept dbDept = sysDeptService.getOne(
                new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptId, dbUser.getDeptId())
                        .eq(SysDept::getDelFlag, UserConstants.DEPT_NORMAL)
                        .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
        );

        // 查询用户所拥有的角色
        List<SysRole> dbRoleList=this.sysRoleService.findRoleByUserId(dbUser.getUserId());


        Set<String> permission=new HashSet<>();
        //判断角色是否包含超级管理员
        long count=dbRoleList.stream().filter(role-> Constants.SUPER_ADMIN.equals(role.getRoleKey())).count();
        if(count>0L){
            // 超级管理员
            permission.add(Constants.ALL_PERMISSION);
        }else{
            // 查询用户所拥有的权限
            Set<Long> roleIdSet=dbRoleList.stream().map(SysRole::getRoleId).collect(Collectors.toSet());
            if(!roleIdSet.isEmpty()) {
                permission = this.sysMenuService.findPermissionsByRoleIds(roleIdSet);
            }
        }

        //组装返回对象
        dbUser.setLoginIp(IpUtils.getIpAddr());
        AdminUserResp adminUserResp=new AdminUserResp(dbUser,dbRoleList,dbDept);
        adminUserResp.setLoginLocation(AddressUtils.getRealAddressByIP(adminUserResp.getLoginIp()));

        return new AdminUserDetails(permission,adminUserResp);
    }
}
